<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        const PENDING = 'pending'
        const RESOLVED = 'resolved'
        const REJECTED = 'rejected'
        class MyPromise {
            status = undefined
            result = ''
            handlers = []
            constructor(executor) {
                this.status = PENDING
                const resolve = (res) => {
                    this.changeStatus(RESOLVED, res)
                }
                const reject = (err) => {
                    this.changeStatus(REJECTED, err)
                }

                executor(resolve, reject)
            }

            changeStatus(status, result) {
                if (this.status === PENDING) {
                    this.status = status
                    this.result = result
                    this.run()
                }
            }

            isPromise(data) {
                if (data !== null && (typeof value === 'function' || typeof value === 'object') && value.then) {
                    return true
                } else {
                    return false
                }
            }

            runMicroTask(task) {
                setTimeout(task, 1000);
            }

            runOne(callback, resolve, reject) {
                if (typeof callback !== 'function') {
                    const settle = this.status === RESOLVED ? resolve : reject
                    settle(this.result)
                } else {
                    try {
                        const data = callback(this.result)
                        if (this.isPromise(data)) {
                            data.then(resolve, reject)
                        }
                        resolve(data)
                    } catch (e) {
                        reject(e)
                    }
                }
            }

            run() {
                this.runMicroTask(() => {

                    if (this.status === PENDING) return

                    while (this.handlers.length) {
                        const { onFulfulled, onRejected, resolve, reject } = this.handlers.shift()

                        if (this.status === RESOLVED) {
                            this.runOne(onFulfulled, resolve, reject)
                        }

                        if (this.status === REJECTED) {
                            this.runOne(onRejected, resolve, reject)
                        }
                    }
                })
            }

            then(onFulfulled, onRejected) {
                return new MyPromise((resolve, reject) => {
                    this.handlers.push({ onFulfulled, onRejected, resolve, reject })
                    this.run()
                })
            }
        }

        new MyPromise((resolve, reject) => {
            setTimeout(() => {
                reject(456)
                // resolve(123)
            }, 1000);
        })
        .then(
            res => {
                console.log(res)
                return 'helow11'
                },
            err => {
                console.log(err)
                return 'i am err'
            }
        )    
        .then(
            res => {
                console.log(res)
                // throw 'run err'
                return 'finllay'
            },
            err => {
                console.log(err)
                return 'err has'
            }
        )
        .then(
            res => {console.log(res)},
            err => {console.log(err)}
        )
    </script>
</body>

</html>